package com.qsw.httpnetlib.net.core;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.qsw.httpnetlib.net.core.callback.OnNetCallback;
import com.qsw.httpnetlib.net.core.utils.HttpsUtils;

import org.jetbrains.annotations.NotNull;
import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * 基本网络操作核心实现
 */
class NetCore {
    private static final String TAG = "TAG_NetCore";

    private OkHttpClient mOkHttpClient;

    private static NetCore mNetCore;

    private static Handler mHandler = new Handler(Looper.getMainLooper());

    private NetCore() {
        init();
    }

    public static NetCore getInstance() {
        if (mNetCore == null) {
            synchronized (NetCore.class) {
                if (mNetCore == null) {
                    mNetCore = new NetCore();
                }
            }
        }
        return mNetCore;
    }

    private void init() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        HttpsUtils.SSLParams sslParams = null;
        try {
            if (NetConfig.CONTEXT != null && NetConfig.ASSETS_HTTPS_CER_FILENAME != null) {
                sslParams = HttpsUtils.getSslSocketFactory(NetConfig.CONTEXT.getAssets().open(NetConfig.ASSETS_HTTPS_CER_FILENAME));
            } else if (NetConfig.HTTPS_CER_FILE != null) {
                sslParams = HttpsUtils.getSslSocketFactory(new FileInputStream(NetConfig.HTTPS_CER_FILE));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (sslParams != null) {
            // 配置HTTPS主要是以下两个方法
            // 当前的trustManager和UnSafeHostnameVerifier均为不安全的配置
            builder.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager);
            builder.hostnameVerifier(HttpsUtils.UnSafeHostnameVerifier);
        }

        if (NetConfig.TIMEOUT_READ != Integer.MIN_VALUE) {
            builder.readTimeout(NetConfig.TIMEOUT_READ, TimeUnit.MILLISECONDS);
        }

        mOkHttpClient = builder.build();
    }

    /**
     * 图片上传
     *
     * @param url            请求地址
     * @param uploadImageKey 上传图片时该文件对应的参数Key
     * @param imageFileName  要上传的图片文件名
     * @param imageData      要上传的图片字节数据
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @param params         请求参数
     * @param onNetCallback  网络事件回调
     */
    void uploadImage(String url, String uploadImageKey, String imageFileName, byte[] imageData, final List<String> pathSegments, final Map<String, String> queryParameter,
                     Map<String, String> headers, Map<String, String> params, final OnNetCallback onNetCallback) {
        uploadFileCore(url, uploadImageKey, imageFileName, MultipartBody.create(imageData, MediaType.parse("image/jpeg")), pathSegments, queryParameter, headers, params, onNetCallback);
    }

    /**
     * 文件上传
     *
     * @param url            请求地址
     * @param uploadFileKey  上传文件时该文件对应的参数Key
     * @param uploadFile     要上传的文件
     * @param fileMIME       要上传的文件类型
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @param params         请求参数
     * @param onNetCallback  网络事件回调
     */
    void uploadFile(String url, String uploadFileKey, File uploadFile, String fileMIME, final List<String> pathSegments, final Map<String, String> queryParameter,
                    Map<String, String> headers, Map<String, String> params, final OnNetCallback onNetCallback) {
        uploadFileCore(url, uploadFileKey, uploadFile.getName(), MultipartBody.create(uploadFile, MediaType.parse(fileMIME)), pathSegments, queryParameter, headers, params, onNetCallback);
    }

    /**
     * 文件上传
     *
     * @param url            请求地址
     * @param uploadFileKey  上传文件时该文件对应的参数Key
     * @param uploadFileName 要上传的文件名
     * @param uploadFileBody 请求体
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @param params         请求参数
     * @param onNetCallback  网络事件回调
     */
    private void uploadFileCore(String url, String uploadFileKey, String uploadFileName, RequestBody uploadFileBody, final List<String> pathSegments, final Map<String, String> queryParameter,
                                Map<String, String> headers, Map<String, String> params, final OnNetCallback onNetCallback) {
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();

        // 添加路径段参数
        if (pathSegments != null && !pathSegments.isEmpty()) {
            for (String pathSegment : pathSegments) {
                urlBuilder.addPathSegment(pathSegment);
            }
        }

        // 添加路径参数
        if (queryParameter != null && !queryParameter.isEmpty()) {
            Set<String> keySet = queryParameter.keySet();
            for (String key : keySet) {
                if (queryParameter.get(key) != null) {
                    urlBuilder.addQueryParameter(key, queryParameter.get(key));
                }
            }
        }

        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        builder.addFormDataPart(uploadFileKey, uploadFileName, uploadFileBody);
        if (params != null) {
            Set<String> keySet = params.keySet();
            for (String key : keySet) {
                builder.addFormDataPart(key, params.get(key));
            }
        }
        Request.Builder requestBuilder = new Request.Builder();
        if (headers != null) {
            Set<String> keySet = headers.keySet();
            for (String key : keySet) {
                requestBuilder.header(key, headers.get(key));
            }
        }
        Request request;
        try {
            request = requestBuilder.url(urlBuilder.build()).post(builder.build()).build();
        } catch (final IllegalArgumentException e) {
            if (onNetCallback != null) {
                runOnUIThread(new Runnable() {
                    @Override
                    public void run() {
                        onNetCallback.onError(e);
                        onNetCallback.onComplete();
                    }
                });
            }
            throw e;
        }

        if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
            Log.d(TAG, "Request=" + request + " ## params=" + (params != null && !params.isEmpty() ? params.toString() : ""));
        }

        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull final IOException e) {
                if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
                    Log.d(TAG, "onFailure ## Request=" + call.request() + " ## errorMsg=" + e.getMessage());
                }
                e.printStackTrace();
                if (onNetCallback != null) {
                    runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            onNetCallback.onError(e);
                            onNetCallback.onComplete();
                        }
                    });
                }
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull final Response response) throws IOException {
                final String str = response.body().string();
                if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
                    Log.d(TAG, "onResponse ## Request=" + call.request() + " ## responseCode=" + response.code() + " ## responseBody=" + str);
                }
                if (onNetCallback != null) {
                    runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            if (response.code() == 200) {
                                onNetCallback.onSuccess(str);
                            } else {
                                onNetCallback.onFailure(response.code(), str);
                            }
                            onNetCallback.onComplete();
                        }
                    });
                }
            }
        });
    }

    /**
     * 异步请求
     *
     * @param isPost         true：使用post；false：使用put
     * @param url            请求地址
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @param params         请求参数
     * @param onNetCallback  网络事件回调
     * @param isDownload     该次请求是否为下载文件
     */
    void postOrPutAsynch(boolean isPost, String url, final List<String> pathSegments, final Map<String, String> queryParameter,
                         Map<String, String> headers, Map<String, String> params, final OnNetCallback onNetCallback, final boolean isDownload) {
        if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
            Log.d(TAG, "PreRequest=" + url + " ## params=" + params.toString());
        }
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null) {
            Set<String> keySet = params.keySet();
            for (String key : keySet) {
                builder.add(key, params.get(key));
            }
        }
        postOrPutAsynchCore(isPost, url, pathSegments, queryParameter, headers, builder.build(), onNetCallback, isDownload);
    }

    /**
     * 异步请求数据
     *
     * @param isPost         true：使用post；false：使用put
     * @param url            请求地址
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @param contentType    contentType
     * @param content        content
     * @param onNetCallback  网络事件回调
     * @param isDownload     该次请求是否为下载文件
     */
    void postOrPutAsynch(boolean isPost, String url, final List<String> pathSegments, final Map<String, String> queryParameter,
                         Map<String, String> headers, String contentType, String content, final OnNetCallback onNetCallback, final boolean isDownload) {
        if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
            Log.d(TAG, "PreRequest=" + url + " ## contentType=" + contentType + " ## content=" + content);
        }
        RequestBody requestBody = RequestBody.create(MediaType.parse(contentType), content);
        postOrPutAsynchCore(isPost, url, pathSegments, queryParameter, headers, requestBody, onNetCallback, isDownload);
    }

    /**
     * 异步请求数据
     *
     * @param isPost         true：使用post；false：使用put
     * @param url            请求地址
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @param contentType    contentType
     * @param content        content
     * @param onNetCallback  网络事件回调
     * @param isDownload     该次请求是否为下载文件
     */
    void postOrPutAsynch(boolean isPost, String url, final List<String> pathSegments, final Map<String, String> queryParameter,
                         Map<String, String> headers, String contentType, byte[] content, final OnNetCallback onNetCallback, final boolean isDownload) {
        if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
            Log.d(TAG, "PreRequest=" + url + " ## contentType=" + contentType + " ## contentByteLength=" + content.length);
        }
        RequestBody requestBody = RequestBody.create(MediaType.parse(contentType), content);
        postOrPutAsynchCore(isPost, url, pathSegments, queryParameter, headers, requestBody, onNetCallback, isDownload);
    }

    /**
     * 异步请求JSON
     *
     * @param isPost         true：使用post；false：使用put
     * @param url            请求地址
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @param params         请求参数
     * @param onNetCallback  网络事件回调
     * @param isDownload     该次请求是否为下载文件
     */
    void postOrPutRequestJsonAsynch(boolean isPost, String url, final List<String> pathSegments, final Map<String, String> queryParameter,
                                    Map<String, String> headers, Map<String, String> params, final OnNetCallback onNetCallback, final boolean isDownload) {
        JSONObject jsonObject = new JSONObject(params);
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonObject.toString());
        if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
            Log.d(TAG, "PreRequest=" + url + " ## jsonObject=" + jsonObject);
        }
        postOrPutAsynchCore(isPost, url, pathSegments, queryParameter, headers, requestBody, onNetCallback, isDownload);
    }

    /**
     * 异步请求JSON
     *
     * @param isPost         true：使用post；false：使用put
     * @param url            请求地址
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @param json           请求json字符串
     * @param onNetCallback  网络事件回调
     * @param isDownload     该次请求是否为下载文件
     */
    void postOrPutRequestJsonAsynch(boolean isPost, String url, final List<String> pathSegments, final Map<String, String> queryParameter,
                                    Map<String, String> headers, String json, final OnNetCallback onNetCallback, final boolean isDownload) {
        if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
            Log.d(TAG, "PreRequest=" + url + " ## json=" + json);
        }
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
        postOrPutAsynchCore(isPost, url, pathSegments, queryParameter, headers, requestBody, onNetCallback, isDownload);
    }

    /**
     * 异步Post或Put请求核心代码
     *
     * @param isPost         true：使用post；false：使用put
     * @param url            请求地址
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @param requestBody    请求体
     * @param onNetCallback  网络事件回调
     * @param isDownload     该次请求是否为下载文件
     */
    private void postOrPutAsynchCore(boolean isPost, String url, final List<String> pathSegments, final Map<String, String> queryParameter,
                                     Map<String, String> headers, RequestBody requestBody, final OnNetCallback onNetCallback, final boolean isDownload) {
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();

        // 添加路径段参数
        if (pathSegments != null && !pathSegments.isEmpty()) {
            for (String pathSegment : pathSegments) {
                urlBuilder.addPathSegment(pathSegment);
            }
        }

        // 添加路径参数
        if (queryParameter != null && !queryParameter.isEmpty()) {
            Set<String> keySet = queryParameter.keySet();
            for (String key : keySet) {
                if (queryParameter.get(key) != null) {
                    urlBuilder.addQueryParameter(key, queryParameter.get(key));
                }
            }
        }

        Request.Builder requestBuilder = new Request.Builder();
        if (headers != null) {
            Set<String> keySet = headers.keySet();
            for (String key : keySet) {
                requestBuilder.header(key, headers.get(key));
            }
        }
        // csrf校验，测试至少需要这两个header，但仍然没有通过，显示校验失败
//        requestBuilder.header("Cookie", "csrftoken=iqFkf1glgLVgrE5cOWcWjQJyNE78igliouuwwFIOXNVMl4kUxaBBWRu9spSZB69N")
//        requestBuilder.header("Referer", "https://192.168.3.57:8809/swbill/account/register/")
        Request request;
        try {
            requestBuilder = requestBuilder.url(urlBuilder.build());
            if (isPost) {
                requestBuilder = requestBuilder.post(requestBody);
            } else {
                requestBuilder = requestBuilder.put(requestBody);
            }
            request = requestBuilder.build();
        } catch (final IllegalArgumentException e) {
            if (onNetCallback != null) {
                runOnUIThread(new Runnable() {
                    @Override
                    public void run() {
                        onNetCallback.onError(e);
                        onNetCallback.onComplete();
                    }
                });
            }
            throw e;
        }

        if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
            Log.d(TAG, "Request=" + request);
        }

        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull final IOException e) {
                if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
                    Log.d(TAG, "onFailure ## Request=" + call.request() + " ## errorMsg=" + e.getMessage());
                }
                e.printStackTrace();
                if (onNetCallback != null) {
                    runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            onNetCallback.onError(e);
                            onNetCallback.onComplete();
                        }
                    });
                }
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull final Response response) throws IOException {
                if (isDownload) {
                    if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
                        Log.d(TAG, "onResponse isDownload ## Request=" + call.request() + " ## responseCode=" + response.code() + " ## ContentLength=" + response.header("Content-Length"));
                    }
                    final InputStream is = response.body().byteStream();
                    if (onNetCallback != null) {
                        if (response.code() == 200) {
                            runOnUIThread(new Runnable() {
                                @Override
                                public void run() {
                                    String lengthStr = response.header("Content-Length");
                                    int length = (lengthStr != null && lengthStr.matches("[0-9]+")) ? Integer.valueOf(lengthStr) : -1;
                                    onNetCallback.onSuccess(is, length);
                                    onNetCallback.onComplete();
                                }
                            });
                        } else {
                            onNetCallback.onFailure(response.code(), response.body().string());
                            onNetCallback.onComplete();
                        }
                    }
                } else {
                    final String str = response.body().string();
                    if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
                        Log.d(TAG, "onResponse ## Request=" + call.request() + " ## responseCode=" + response.code() + " ## responseBody=" + str);
                    }
                    if (onNetCallback != null) {
                        runOnUIThread(new Runnable() {
                            @Override
                            public void run() {
                                if (response.code() == 200) {
                                    onNetCallback.onSuccess(str);
                                } else {
                                    onNetCallback.onFailure(response.code(), str);
                                }
                                onNetCallback.onComplete();
                            }
                        });
                    }
                }
            }
        });
    }

    /**
     * 异步Get或Delete请求
     *
     * @param isGet          true：Get请求；false：Delete请求
     * @param url            请求地址
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @param onNetCallback  网络事件回调
     * @param isDownload     该次请求是否为下载文件
     */
    void getOrDeleteAsynch(boolean isGet, String url, final List<String> pathSegments, final Map<String, String> queryParameter,
                           final Map<String, String> headers, final OnNetCallback onNetCallback, final boolean isDownload) {
        getOrDeleteAsynchCore(isGet, url, pathSegments, queryParameter, headers, onNetCallback, isDownload);
    }

    /**
     * 异步Get或Delete请求核心代码
     *
     * @param isGet          true：Get请求；false：Delete请求
     * @param url            请求地址
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @param onNetCallback  网络事件回调
     * @param isDownload     该次请求是否为下载文件
     */
    private void getOrDeleteAsynchCore(boolean isGet, String url, final List<String> pathSegments, final Map<String, String> queryParameter,
                                       final Map<String, String> headers, final OnNetCallback onNetCallback, final boolean isDownload) {
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();

        // 添加路径段参数
        if (pathSegments != null && !pathSegments.isEmpty()) {
            for (String pathSegment : pathSegments) {
                urlBuilder.addPathSegment(pathSegment);
            }
        }

        // 添加路径参数
        if (queryParameter != null && !queryParameter.isEmpty()) {
            Set<String> keySet = queryParameter.keySet();
            for (String key : keySet) {
                if (queryParameter.get(key) != null) {
                    urlBuilder.addQueryParameter(key, queryParameter.get(key));
                }
            }
        }

        Request.Builder requestBuilder = new Request.Builder();
        // 添加请求头
        if (headers != null) {
            Set<String> keySet = headers.keySet();
            for (String key : keySet) {
                requestBuilder.header(key, headers.get(key));
            }
        }
        // csrf校验，测试至少需要这个header，可以达到使csrftoken值不再变化
//        requestBuilder.header("Cookie", "csrftoken=iqFkf1glgLVgrE5cOWcWjQJyNE78igliouuwwFIOXNVMl4kUxaBBWRu9spSZB69N")
        Request request;
        try {
            requestBuilder = requestBuilder.url(urlBuilder.build());
            if (isGet) {
                requestBuilder = requestBuilder.get();
            } else {
                requestBuilder = requestBuilder.delete();
            }
            request = requestBuilder.build();
        } catch (final IllegalArgumentException e) {
            if (onNetCallback != null) {
                runOnUIThread(new Runnable() {
                    @Override
                    public void run() {
                        onNetCallback.onError(e);
                        onNetCallback.onComplete();
                    }
                });
            }
            throw e;
        }

        if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
            Log.d(TAG, "Request=" + request);
        }

        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull final IOException e) {
                if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
                    Log.d(TAG, "onFailure ## Request=" + call.request() + " ## errorMsg=" + e.getMessage());
                }
                if (onNetCallback != null) {
                    runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            onNetCallback.onError(e);
                            onNetCallback.onComplete();
                        }
                    });
                }
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull final Response response) throws IOException {
                if (isDownload) {
                    if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
                        Log.d(TAG, "onResponse isDownload ## Request=" + call.request() + " ## responseCode=" + response.code() + " ## ContentLength=" + response.header("Content-Length"));
                    }
                    final InputStream is = response.body().byteStream();
                    if (onNetCallback != null) {
                        if (response.code() == 200) {
                            runOnUIThread(new Runnable() {
                                @Override
                                public void run() {
                                    String lengthStr = response.header("Content-Length");
                                    int length = (lengthStr != null && lengthStr.matches("[0-9]+")) ? Integer.valueOf(lengthStr) : -1;
                                    onNetCallback.onSuccess(is, length);
                                    onNetCallback.onComplete();
                                }
                            });
                        } else {
                            onNetCallback.onFailure(response.code(), response.body().string());
                            onNetCallback.onComplete();
                        }
                    }
                } else {
                    final String str = response.body().string();
                    if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
                        Log.d(TAG, "onResponse ## Request=" + call.request() + " ## responseCode=" + response.code() + " ## responseBody=" + str);
                    }
                    if (onNetCallback != null) {
                        runOnUIThread(new Runnable() {
                            @Override
                            public void run() {
                                if (response.code() == 200) {
                                    onNetCallback.onSuccess(str);
                                } else {
                                    onNetCallback.onFailure(response.code(), str);
                                }
                                onNetCallback.onComplete();
                            }
                        });
                    }
                }
            }
        });
    }

    /**
     * 同步Get或Delete请求核心代码
     *
     * @param isGet          true：Get请求；false：Delete请求
     * @param url            请求地址
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @return 返回数据
     * @throws IOException 网络访问异常
     */
    String getOrDeleteSynch(boolean isGet, String url, final List<String> pathSegments, final Map<String, String> queryParameter,
                            final Map<String, String> headers) throws IOException {
        return getOrDeleteSynchCore(isGet, url, pathSegments, queryParameter, headers);
    }

    /**
     * 同步Get或Delete请求核心代码
     *
     * @param isGet          true：Get请求；false：Delete请求
     * @param url            请求地址
     * @param pathSegments   路径段参数
     * @param queryParameter 路径参数
     * @param headers        请求头
     * @return 返回数据
     * @throws IOException 网络访问异常
     */
    private String getOrDeleteSynchCore(boolean isGet, String url, final List<String> pathSegments, final Map<String, String> queryParameter,
                                        final Map<String, String> headers) throws IOException {
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();

        // 添加路径段参数
        if (pathSegments != null && !pathSegments.isEmpty()) {
            for (String pathSegment : pathSegments) {
                urlBuilder.addPathSegment(pathSegment);
            }
        }

        // 添加路径参数
        if (queryParameter != null && !queryParameter.isEmpty()) {
            Set<String> keySet = queryParameter.keySet();
            for (String key : keySet) {
                if (queryParameter.get(key) != null) {
                    urlBuilder.addQueryParameter(key, queryParameter.get(key));
                }
            }
        }

        Request.Builder requestBuilder = new Request.Builder();
        // 添加请求头
        if (headers != null && !headers.isEmpty()) {
            Set<String> keySet = headers.keySet();
            for (String key : keySet) {
                if (headers.get(key) != null) {
                    requestBuilder.header(key, headers.get(key));
                }
            }
        }
        // csrf校验，测试至少需要这个header，可以达到使csrftoken值不再变化
//        requestBuilder.header("Cookie", "csrftoken=iqFkf1glgLVgrE5cOWcWjQJyNE78igliouuwwFIOXNVMl4kUxaBBWRu9spSZB69N")
        requestBuilder = requestBuilder.url(urlBuilder.build());
        if (isGet) {
            requestBuilder = requestBuilder.get();
        } else {
            requestBuilder = requestBuilder.delete();
        }
        Request request = requestBuilder.build();

        String result = null;

        if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
            Log.d(TAG, "Request=" + request);
        }

        try {
            Response response = mOkHttpClient.newCall(request).execute();
            result = response.body().string();

            if (NetConfig.PRINT_REQUEST_RESPONSE_LOG) {
                Log.d(TAG, "onResponse ## Request=" + request + " ## responseCode=" + response.code() + " ## responseBody=" + result);
            }
        } catch (IOException e) {
            throw e;
        }

        return result;
    }

    /**
     * 运行在主线程
     *
     * @param runnable 要运行的代码
     */
    private static void runOnUIThread(Runnable runnable) {
        mHandler.post(runnable);
    }
}
